import {
  Cartesian3,
  Cartographic,
  Math as CesiumMath,
  PolygonHierarchy,
} from "cesium"
import * as turf from "@turf/turf"

//弧度坐标转笛卡尔坐标
export function cartographicToCartesian3(point: Cartographic) {
  return Cartesian3.fromRadians(point.longitude, point.latitude, point.height)
}

//计算任意点到平面的投影
export function projectPointToPlane(
  point: Cartesian3,
  plane: { point: Cartesian3; normal: Cartesian3 },
) {
  const vector = Cartesian3.subtract(point, plane.point, new Cartesian3())
  const dotProduct = Cartesian3.dot(vector, plane.normal)
  const normalDot = Cartesian3.dot(plane.normal, plane.normal)
  const projection = Cartesian3.multiplyByScalar(
    plane.normal,
    dotProduct / normalDot,
    new Cartesian3(),
  )
  return Cartesian3.subtract(point, projection, new Cartesian3())
}

//计算多点的中点
export function center(points: Cartesian3[]) {
  const total = new Cartesian3(0, 0, 0)
  points.forEach((point) => {
    Cartesian3.add(total, point, total)
  })
  return Cartesian3.divideByScalar(total, points.length, new Cartesian3())
}

//计算面积
export function getPolygonArea(polygonHierarchy: PolygonHierarchy) {
  const polygon = polygonToGeojson(polygonHierarchy)
  const area = turf.area(polygon)
  return area
}

//点转经纬度
export function pointToLngLat(point: Cartesian3): GeoJSON.Position {
  const { longitude, latitude, height } = Cartographic.fromCartesian(point)
  return [
    CesiumMath.toDegrees(longitude),
    CesiumMath.toDegrees(latitude),
    height,
  ]
}

//多边形转geojson
export function polygonToGeojson(
  polygon: PolygonHierarchy,
): GeoJSON.Feature<GeoJSON.Polygon> {
  const positions = polygon.positions.map((item) => pointToLngLat(item))
  const holes = polygon.holes
  const data: GeoJSON.Feature<GeoJSON.Polygon> = {
    type: "Feature",
    geometry: {
      type: "Polygon",
      coordinates: [[...positions, positions[0]]],
    },
    properties: {},
  }
  if (holes) {
    holes.forEach((hole) => {
      const positions = hole.positions.map((hole) => pointToLngLat(hole))
      data.geometry.coordinates.push([...positions, positions[0]])
    })
  }
  return data
}
